<?php 

class Field {
	
	var $_html;
	var $_error;
	var $_value;
	var $_required;
	
	public function __construct(){
		$this->_error = FALSE;
		$this->_required = TRUE;
		$this->_value = NULL;
	}
	
	public function clean(){
		$this->_value = NULL;
		$this->_error = FALSE;
	}
	
	public function containsError(){
		return $this->_error;
	}
	
	public function isRequired(){
		return $this->_required;
	}
	
	public function isValid(){
		$valid = $this->getValue();
		$valid = (!empty($valid));
		if($valid === FALSE){
			$this->_error = TRUE;
		}
		return $valid;
	}
		
	public function getValue(){
		return $this->_value;
	}
	
	public function setValue($value){
		if($value != NULL && is_string($value)){
			$value = trim($value);
		}
		$this->_value = $value;
	}
	
	public function render($name, $attrs = array()){
		throw new Exception("Please, implement render");
	}
	
	protected function base_render($name, $attrs = array()){
		$attrs["name"] = $name;
		$attrs["id"] = $name;
		$attrs["value"] = $this->_value;
		return $attrs;
	}
	
}

class CharField extends Field {
	
	public function __construct(){
		parent::__construct();
		$this->_html = new Html("input", array("type" => "text"), FALSE);
	}
	
	public function render($name, $attrs = array()){
		$attrs = $this->base_render($name, $attrs);
		return $this->_html->render($name, $attrs);
	}
		
}

class IntegerField extends CharField {
	
	public function isValid(){
		if($this->getValue() === NULL){
			$this->_error = TRUE;
			return FALSE;
		}
		return TRUE;
	}
	
	public function getValue(){
		$value = parent::getValue();
		if(!empty($value) && is_numeric($value)){
			return (int) $value;
		}
		return NULL;
	}
	
	public function setValue($value){
		if(!empty($value) && is_numeric($value)){
			$this->_value = $value;
		}
	}
	
}

class BooleanField extends Field {
	
	var $checked;
	
	public function __construct($value = 1){
		parent::__construct();
		$this->_html = new Html("input", array("type" => "checkbox"), FALSE);
		$this->checked = FALSE;
		$this->_value = $value;
	}
	
	public function render($name, $attrs = array()){
		if($this->checked){
			$attrs["checked"] = "checked";
		}
		$attrs = $this->base_render($name, $attrs);
		return $this->_html->render($name, $attrs);
	}
	
	public function setValue($value){
		if(!empty($value) && is_bool($value)){
			$this->checked = (bool) $value;
		} else {
			if($value == $this->_value){
				$this->checked = TRUE;
			} else {
				$this->checked = FALSE;
			}
		}
	}
	
	public function getValue(){
		return $this->checked;
	}
	
	public function clean(){
		$this->checked = FALSE;
		$this->_error = FALSE;
	}
	
}

class TextField extends Field {
	
	public function __construct(){
		parent::__construct();
		$this->_html = new Html("textarea");
	}
	
	public function render($name, $attrs = array()){
		$attrs = $this->base_render($name, $attrs);
		return $this->_html->render($name, $attrs);
	}
	
}

class SelectField extends Field {
	
	var $_data;
	
	public function __construct($data = array()){
		parent::__construct();
		$this->_data = $data;
		$this->_html = new Html("select");
	}
	
	public function render($name, $attrs = array()){
		$attrs = $this->base_render($name, $attrs);
		$this->_html->setInner($this->_buildOptions());
		if(array_key_exists("value", $attrs)){
			unset($attrs["value"]);
		}
		return $this->_html->render($name, $attrs);
	}
	
	private function _buildOptions(){
		$options = array();
		foreach($this->_data as $option){
			$options[] = $option->render($option->getValue() == $this->getValue());
		}
		return implode("", $options);
	}
	
}

